package com.lagou.controller;

import com.lagou.dao.TokenDao;
import com.lagou.dao.UserDao;
import com.lagou.model.Token;
import com.lagou.model.User;
import com.lagou.service.CodeService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 用户控制器
 */
@RestController
@RequestMapping("/user")
public class UserController {
    /**
     * 验证码服务
     */
    @Reference
    private CodeService codeService;

    /**
     * 用户DAO
     */
    @Autowired
    private UserDao userDao;

    /**
     * Token的DAO
     */
    @Autowired
    private TokenDao tokenDao;

    /**
     * 注册用户
     *
     * @param email 用户邮箱
     * @param password 用户密码
     * @param code 验证码
     * @return 操作结果
     */
    @GetMapping("/register/{email}/{password}/{code}")
    public boolean registerUser(@PathVariable("email") String email,
                                @PathVariable("password") String password, @PathVariable("code") String code) {
        // 判断验证码是否有效
        if (!validateCode(email, code)) {
            System.out.println(String.format("Code %s of %s is invalid!", code, email));
            return false;
        }

        // 判断用户是否已经存在
        if (existUser(email)) {
            return false;
        }

        // 保存用户信息
        return saveUser(email, password);
    }

    /**
     * 判断用户是否已经注册
     *
     * @param email 用户邮箱
     * @return 判断结果
     */
    @GetMapping("/isRegistered/{email}")
    public boolean isRegistered(@PathVariable("email") String email) {
        return existUser(email);
    }

    /**
     * 登录接口
     *
     * @param email 用户邮箱
     * @param password 用户密码
     * @param response 登录响应
     * @return 操作结果
     */
    @GetMapping("/login/{email}/{password}")
    public boolean login(@PathVariable("email") String email,
                         @PathVariable("password") String password, HttpServletResponse response) {
        // 校验用户信息
        if (!validateUser(email, password)) {
            System.out.println(String.format("Failed to check %s", email));
            return false;
        }

        // 生成Token
        String token = createToken(email, password);
        if (token.isEmpty()) {
            System.out.println(String.format("Failed to create token for %s", email));
            return false;
        }

        Cookie cookie = new Cookie("token", token);
        cookie.setDomain("www.test.com");
        cookie.setPath("/");

        cookie.setMaxAge(600000);
        response.addCookie(cookie);

        return true;
    }

    /**
     * 查询用户邮箱
     *
     * @param token 用户Token
     * @return 用户邮箱
     */
    @GetMapping("/info/{token}")
    public String queryEmail(@PathVariable("token") String token) {
        Token tokenInfo = new Token();
        tokenInfo.setToken(token);

        Example<Token> example = Example.of(tokenInfo);
        try {
            List<Token> tokens = tokenDao.findAll(example);
            if (tokens.isEmpty()) {
                return null;
            }

            return tokens.get(0).getEmail();
        } catch (Exception ex) {
            System.out.println(String.format("Failed to query token information of %s", token));
            ex.printStackTrace();
        }

        return null;
    }

    /**
     * 删除Token
     *
     * @param email 用户邮箱
     * @return 操作结果
     */
    private boolean deleteToken(String email) {
        Token token = new Token();
        token.setEmail(email);

        Example<Token> example = Example.of(token);
        try {
            List<Token> tokens = tokenDao.findAll(example);
            for (Token curToken : tokens) {
                tokenDao.delete(token);
            }

            return  true;
        } catch (Exception ex) {
            System.out.println(String.format("Failed to delete tokens of %s", email));
            ex.printStackTrace();
        }

        return false;
    }

    /**
     * 生成Token
     *
     * @param email 用户邮箱
     * @param password 用户密码
     * @return 生成的Token
     */
    private String createToken(String email, String password) {
        if (!deleteToken(email)) {
            System.out.println(String.format("Failed to delete old tokens of %s", email));
            return "";
        }

        Token token = new Token();
        token.setEmail(email);
        token.setToken(String.format("%s|%s", email, password));

        try {
            tokenDao.save(token);
            return token.getToken();
        } catch (Exception ex) {
            System.out.println(String.format("Failed to save token of %s", email));
            ex.printStackTrace();
        }

        return "";
    }

    /**
     * 校验用户信息
     *
     * @param email 用户邮箱
     * @param password 用户密码
     * @return 校验结果
     */
    private boolean validateUser(String email, String password) {
        User user = new User();
        user.setEmail(email);
        user.setPassword(password);

        Example<User> example = Example.of(user);
        try {
            return userDao.exists(example);
        } catch (Exception ex) {
            System.out.println(String.format("Failed to query information of %s", email));
            ex.printStackTrace();
        }

        return false;
    }

    /**
     * 校验验证码
     *
     * @param email 用户邮箱
     * @param code 验证码
     * @return 校验结果
     */
    private boolean validateCode(String email, String code) {
        try {
            int result = codeService.validateCode(email, code);
            return result == 0;
        } catch (Exception ex) {
            System.out.println(String.format("Failed to check code %s of %s", code, email));
            ex.printStackTrace();
        }

        return false;
    }

    /**
     * 保存用户信息
     *
     * @param email 用户邮箱
     * @param password 用户密码
     * @return 操作结果
     */
    private boolean saveUser(String email, String password) {
        User user = new User();
        user.setEmail(email);
        user.setPassword(password);

        try {
            userDao.save(user);
            return true;
        } catch (Exception ex) {
            System.out.println(String.format("Failed to save user information of %s", email));
            ex.printStackTrace();
        }

        return false;
    }

    /**
     * 判断用户是否已经存在
     *
     * @param email 邮箱地址
     * @return 判断结果
     */
    private boolean existUser(String email) {
        User user = new User();
        user.setEmail(email);

        Example<User> example = Example.of(user);
        try {
            List<User> users = userDao.findAll(example);
            return !users.isEmpty();
        } catch (Exception ex) {
            System.out.println(String.format("Failed to query information of %s", email));
            ex.printStackTrace();
        }

        return true;
    }
}
